package ccm.component.oscilloscope;

import java.util.ArrayList;
import java.util.Collection;

public class ChunkList<E>
{
    static final int chunkBit=20;
    static final int chunkMask=((1<<chunkBit)-1);
    private final ArrayList<E[]> array;
    private int size;
    final Object addLock;

    public ChunkList()
    {
        array=new ArrayList<>();
        size=0;
        addLock=new Object();
    }

    public void clear()
    {
        array.clear();
        size=0;
    }

    public int size()
    {
        return size;
    }

    public E get(int i)
    {
        if(i>=size)
        {
            throw new IndexOutOfBoundsException();
        }
        synchronized(array)
        {
            return array.get(i>>chunkBit)[i&chunkMask];
        }
    }


    public void addAll(Collection<? extends E> c)
    {
        synchronized(addLock)
        {
            if(array.size()<=(size+c.size())>>chunkBit)
            {
                synchronized(array)
                {
                    while(array.size()<=(size+c.size())>>chunkBit)
                    {
                        array.add((E[])new Object[(1<<chunkBit)]);
                    }
                }
            }
            c.forEach(x->
            {
                array.get(size>>chunkBit)[size&chunkMask]=x;
                size+=1;
            });
        }
    }

    public void add(E c)
    {
        synchronized(addLock)
        {
            if(array.size()<=((size+1)>>chunkBit))
            {
                synchronized(array)
                {
                    array.add((E[])new Object[(1<<chunkBit)]);
                }
            }
            array.get(size>>chunkBit)[size&chunkMask]=c;
            size+=1;
        }
    }
}
